package com.moli.iov.down.command.codec.encode;

import com.moli.iov.exception.BusinessException;
import com.moli.iov.protocol.util.BccUtils;
import com.moli.iov.util.NumberUtil;
import com.moli.iov.util.StringUtil;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 *  指令协议封装
 * </p>
 *
 * @author: zql
 * @Date: 2018/11/27 15:28
 */
public class ProtocolEncoder {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 协议头 2字节
     */
    private byte[] startTag = {0x23,0x23};

    /**
     * 命令标识 1字节
     */
    private byte[] commandTag;

    /**
     * 应答标志 1字节
     */
    private byte[] responseTag = StringUtil.hexStringToByte("FE");

    /**
     * 唯一识别码 VIN 17字节
     */
    private byte[] vin;

    /**
     * 加密码方式 1字节
     * 0x01：数据不加密；0x02：数据经过 RSA 算法加密；0x03：数据经过
     * AES128 位算法加密；“0xFE”表示异常，“0xFF”表示无效，其他预
     * 留
     */
    private byte[] encryptTag = {0x01};

    /**
     * 数据单元长度 2字节
     */
    private byte[] dataLen;

    /**
     * 数据单元
     */
    private byte[] data;

    /**
     * 校验码 1字节
     */
    private byte[] checkCode;

    public ProtocolEncoder(byte commandTag, byte[] vin, byte[] data) {
        byte[] commandTags = {commandTag};
        this.commandTag = commandTags;
        this.vin = vin;
        this.data = data;
        this.dataLen = NumberUtil.intToHexToByte(data.length, 4);
    }

    /**
     * 设置命令标识
     * @param commandTag
     * @return
     */
    public ProtocolEncoder setCommandTag(byte[] commandTag){
        this.commandTag = commandTag;
        return this;
    }

    /**
     * 设置 应答标志
     * @param responseTag
     * @return
     */
    public ProtocolEncoder setResponseTag(byte[] responseTag){
        this.responseTag = responseTag;
        return this;
    }
    /**
     * 设置唯一识别码 VIN
     * @param vin
     * @return
     */
    public ProtocolEncoder setVin(byte[] vin){
        this.vin = vin;
        return this;
    }

    /**
     * 设置数据单元
     * @param data
     * @return
     */
    public ProtocolEncoder setData(byte[] data){
        this.data = data;
        this.dataLen = NumberUtil.intToHexToByte(data.length, 4);
        return this;
    }

    /**
     * 指令封装
     * @return
     */
    public byte[] endcode(){
        if(commandTag == null || commandTag.length == 0){
            logger.error("指令封装异常，命令标识为空");
            throw new BusinessException("命令标识为空");
        }

        if(vin == null || vin.length == 0){
            logger.error("指令封装异常，唯一识别码为空");
            throw new BusinessException("唯一识别码为空");
        }

        if(dataLen == null || dataLen.length == 0){
            logger.error("指令封装异常，数据单元长度为空");
            throw new BusinessException("数据单元长度为空");
        }

        if(data == null || data.length == 0){
            logger.error("指令封装异常，数据单元长度为空");
            throw new BusinessException("数数据单元为空");
        }

        byte[] all = ArrayUtils.addAll(startTag, commandTag);
        all = ArrayUtils.addAll(all, responseTag);
        all = ArrayUtils.addAll(all, vin);
        all = ArrayUtils.addAll(all, encryptTag);
        all = ArrayUtils.addAll(all, dataLen);
        all = ArrayUtils.addAll(all, data);
        if(checkCode == null || checkCode.length == 0){
            all = BccUtils.bccBodyEncode(all);
        }
        return all;
    }
}
